using System;
using System.IO;

namespace kerberosLibs
{
	/// <summary>
	/// Summary description for TaskSSH. We establish a connection to a remote machine and provide a
	/// IP "tunnel". We don't really support a back and forth conversation.
	/// </summary>
	public class TaskSSHTunnel : LoggingConnectionTask
	{
		public TaskSSHTunnel()
		{
		}

		/// <summary>
		/// Number of steps to complete this guy
		/// </summary>
		public override int NumberOfSteps
		{
			get
			{
				return 4;
			}
		}

		private int _vncLocalPort;
		private int _vncRemotePort;
		private string _remoteMachine;
		private string _username;

		/// <summary>
		/// Get/Set where we should have the local port appear
		/// </summary>
		public int TunneledLocalPort 
		{
			get {return _vncLocalPort;}
			set {_vncLocalPort = value;}
		}

		/// <summary>
		/// Get/Set the Remote machine port that should be attched to the TunneledLocalPort.
		/// </summary>
		public int TunneledRemotePort
		{
			get {return _vncRemotePort;}
			set {_vncRemotePort = value;}
		}

		/// <summary>
		/// Get/Set the DNS/IP name of remote machine.
		/// </summary>
		public string RemoteMachine
		{
			get {return _remoteMachine;}
			set {_remoteMachine = value;}
		}

		/// <summary>
		/// Get/Set the Remote Username (to use with ssh).
		/// </summary>
		public string RemoteUserName
		{
			get {return _username;}
			set {_username = value;}
		}

		/// <summary>
		/// Get/Set the # of lines we should see back from host before deciding the tunnel has
		/// been established.
		/// </summary>
		public int LinesSeenBeforeDone 
		{
			get {return _linesToEstablish;}
			set {_linesToEstablish = value;}
		}
		private int _linesToEstablish = 5;

		/// <summary>
		/// Establish the ssh connection
		/// </summary>
		public override void Start()
		{
			///
			/// Build up a command that will run the ssh program.
			/// 

			FileInfo ssh_exe = kerberosLibs.kerberosProductAccess.SSHPath;
			System.Text.StringBuilder bld = new System.Text.StringBuilder();
			//bld.AppendFormat (@"-g -t -L {0}:{2}:{1} -t {3}@{2}",
			//	new object[4] {_vncLocalPort, _vncRemotePort, _remoteMachine, _username});
            bld.AppendFormat(@"-R {0}:{2}:{1} -t {3}@{2}",
                new object[4] { _vncLocalPort, _vncRemotePort, _remoteMachine, _username });
            string ssh_args = bld.ToString();

			///
			/// Get ourselves setup to go!
			/// 

			OnUIStatusUpdate (0, "Starting SSH");
			InitProcess (ssh_exe, ssh_args);
			_linecount = 0;
			_proc.OnProcessOutputLine += new kerberosLibs.ProcessWatcher.ProcessOutputLine(_proc_OnProcessOutputLine);
			StartProcess ();
			OnUIStatusUpdate (1, "Waiting for SSH to connect");
		}

		/// <summary>
		/// Counts the # of lines we've seen come back from the ssh process. That is how we know we've
		/// managed to connect.
		/// </summary>
		private int _linecount = 0;
		private bool _done = false;

		/// <summary>
		/// Count the # of lines that come back from ssh!
		/// </summary>
		/// <param name="line"></param>
		private void _proc_OnProcessOutputLine(string line)
		{
			if (line != null) 
			{
				_linecount++;
				if (!_done) 
				{
					OnUIStatusUpdate (2, "Receiving output from SSH connection");
				}
				if (!_done && _linecount > _linesToEstablish) 
				{
					_done = true;
					OnUIStatusUpdate (3, "SSH Tunnel Established");
					OnTaskDone();
				}
			}
		}
	}
}
